import { Injectable, HttpException, HttpStatus } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm'
import { UserEntity } from './entities/user.entity'
import { RoleService } from 'src/role/role.service'
import { CreateUserDto } from './dto/create-user.dto'
import { UpdateUserDto } from './dto/update-user.dto'
import { MenuService } from '../menu/menu.service';
import { RedisService } from 'src/redis/redis.service'
import { deepClone, compose } from '../utils/util'
interface UserActionData {
  id: string,
  time?: string | number,
  type?: string | number,
}

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(UserEntity)
    private userRepository: Repository<UserEntity>,
    private readonly roleService: RoleService,
    private readonly menuService: MenuService,
    private readonly redisService: RedisService
  ) { }

  /**
   * 账号密码注册
   * @param createUser
   */
  async register(createUser: CreateUserDto) {
    let { username, roles: copyRole = [] } = createUser

    let existUser = await this.queryUserByName(username);
    if (existUser) {
      throw new HttpException('用户名已存在', HttpStatus.BAD_REQUEST)
    }
    //注册用户默认赋值user角色
    let allRole = await this.roleService.getRoleList();
    if (allRole.length == 0) {
      throw new HttpException('角色列表为空，请先添加角色', HttpStatus.BAD_REQUEST)
    }
    let userRole = allRole.find(item => item.name == 'user');
    if (!userRole) {
      throw new HttpException('未找到user角色，请先添加user角色', HttpStatus.BAD_REQUEST)
    }
    copyRole.push(userRole.id);
    copyRole = [...new Set(copyRole)]
    let role = await this.roleService.getRolesByIds(copyRole);
    const userParam: Partial<UserEntity> = {
      ...createUser,
      roles: role
    }
    const newUser = await this.userRepository.create(userParam)
    return await this.userRepository.save(newUser)
  }

  //判断当前username 是否被占用
  async queryUserByName(username: string): Promise<boolean> {
    const user = await this.userRepository.findOne({
      where: { username: username }
    })
    if (user) {
      return true
    }
    return false
  }

  /**
   * 获取所有用户列表
   * @returns userEntity[]
   */
  async findAll(): Promise<UserEntity[]> {
    let userList = await this.userRepository.find({ relations: ['roles'] });
    let result = []
    if (userList.length > 0) {
      result = userList.filter(user => user.username !== 'admin')
      result.forEach(user => {
        if (user.roles.length > 0) {
          user.roles = user.roles.map(role => {
            return { name: role.name, id: role.id }
          });
        }
      })
    }
    return result
  }

  async findOne(username: string): Promise<UserEntity | undefined> {
    // 因为密码是加密后的，没办法直接对比用户名密码，只能先根据用户名查出用户，再比对密码
    const user = await this.userRepository.createQueryBuilder('user')
      .addSelect('user.password')
      .leftJoinAndSelect('user.roles', 'role')
      .where('user.username=:username', { username })
      .getOne()

    return user
  }

  async findOneById(id: string) {
    return await this.userRepository.findOne({ where: { id }, relations: ['roles'], })
  }


  //获取用户的权限
  async getUserMenus(id: string) {
    const userData = await this.userRepository.findOne({ where: { id }, relations: ['menus', 'menus.children'] });
    let copyMenu = deepClone(userData.menus);
    copyMenu.forEach((item) => {
      if (item.first_menu) {
        copyMenu = compose(item, copyMenu)
      }
    })
    return copyMenu
  }

  //更改用户信息
  async update(updateUserDto: UpdateUserDto): Promise<UserEntity> {
    const { id, menus: copyMenu, roles: copyRole, ...reset } = updateUserDto;
    let existUser = await this.findOneById(id)
    if (!existUser) throw new Error('用户不存在')
    if (updateUserDto.username && updateUserDto.username != existUser.username) {
      let user = await this.queryUserByName(updateUserDto.username);
      if (user) {
        throw new HttpException('用户名已存在', HttpStatus.BAD_REQUEST)
      }
    }
    if (copyMenu) {
      let findMenus = await this.menuService.getMenusByIds(copyMenu);
      if (findMenus.length > 0) {
        existUser.menus = findMenus;
      }
    }
    if (copyRole) {
      let findRoles = await this.roleService.getRolesByIds(copyRole);
      if (findRoles.length > 0) {
        existUser.roles = findRoles;
      }
    }
    Object.assign(existUser, reset)
    return this.userRepository.save(existUser)
  }

  //删除用户
  async remove(id: string) {
    let user = await this.userRepository.findOne({ where: { id: id } });
    if (user) {
      this.userRepository.remove(user)
      return {}
    } else {
      throw new Error('用户不存在')
    }
  }


  //禁用用户
  async banOrOpenUser(data: UserActionData) {
    let user = await this.userRepository.findOne({ where: { id: data.id } });
    if (!user) throw new Error('用户不存在')
    if (data.type == 0 && +data.time < 0) {
      this.userRepository.update(user.id, { status: 0 })
      this.redisService.set(`user:${user.id}`, 0)
    } else if (data.type == 1) {
      this.userRepository.update(user.id, { status: 1 })
      this.redisService.set(`user:${user.id}`, 0, 10)
    } else {
      this.redisService.set(`user:${user.id}`, 0, +data.time)
    }
    return {}
  }
}
